package org.elephas.model;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;

import org.elephas.persistence.Dao;
import org.elephas.persistence.query.QueryParam;
import org.hibernate.Query;
import org.springframework.transaction.annotation.Transactional;

import salve.depend.Dependency;

/**
 * <p>
 * User: Nick Heudecker
 * </p>
 * <p>
 * Date: Jan 27, 2008
 * </p>
 * <p>
 * Time: 5:34:46 PM
 * </p>
 */
@SuppressWarnings({"unchecked"})
@Entity
public class Blog extends AbstractPersistent {

	@Column(length = 100, nullable = false, unique = true)
	private String name;

	@Column(length = 1000)
	private String description;

	@Column(length = 255)
	private String tagline;
	@ManyToMany
	private List<BlogMembership> users;

	@OneToOne(cascade = { CascadeType.ALL })
	@JoinColumn(name = "config_id", unique = true, nullable = false, updatable = false)
	private BlogConfiguration configuration;

	@Dependency
	private Dao dao;

	/**
	 * Loads all categories for this blog.
	 * 
	 * @return a {@link List} of {@link Category} objects
	 */
	public List<Category> getCategories() {
		Query q = dao
				.createQuery("select c from Category c where c.blog = :blog");
		q.setParameter("blog", this);
		return q.list();
	}

	/**
	 * Loads the last <code>nrOfPosts</code> recent {@link Post}s.
	 * 
	 * @param nrOfPosts
	 *            the number of {@link Post}s to return
	 * @return a {@link List} of {@link Post}s
	 */
	public List<Post> getRecentPosts(int nrOfPosts) {
        StringBuilder sb = new StringBuilder();
		sb.append("from Post post");
		sb.append(" where post.blog.uuid = :blogId");
		sb.append(" order by post.created desc");

		Query query = dao.createQuery(sb.toString());
		query.setString("blogId", getUuid());

		query.setMaxResults(nrOfPosts);

		return query.list();
	}

	/**
	 * Loads the {@link BlogRole} the given {@link User} has for this
	 * {@link Blog}.
	 * 
	 * @param user
	 *            the {@link User}
	 * @return the {@link BlogRole} or <code>null</code> in case the user
	 *         doesn't have a {@link BlogRole} on this {@link Blog}.
	 */
	public BlogRole getBlogRoleForUser(User user) {
		Query query = dao
				.createQuery("select ms.blogRole from BlogMembership ms "
						+ "where ms.user = :user and ms.blog = :blog");
		query.setParameter("user", user);
		query.setParameter("blog", this);
		return (BlogRole) query.uniqueResult();
	}

	/**
	 * Loads all {@link User}s associated with this {@link Blog}.
	 * 
	 * @return a {@link List} of {@link User}s
	 */
	public List<User> getUsers(QueryParam param) {
		Query query = dao.createQuery("select ms.user from BlogMembership ms"
				+ " where ms.blog = :blog", param);
		query.setParameter("blog", this);
		return query.list();
	}

	/**
	 * Loads all {@link BlogMembership}s for this {@link Blog}.
	 * 
	 * @return a {@link List} of {@link BlogMembership}s
	 */
	public List<BlogMembership> getMemberships(QueryParam param) {
		Query query = dao.createQuery("select ms from BlogMembership ms"
				+ " where ms.blog = :blog", param);
		query.setParameter("blog", this);
		return query.list();
	}

	public int countMemberships() {
		Query query = dao.createQuery("select count(ms) from BlogMembership ms"
				+ " where ms.blog = :blog");
		query.setParameter("blog", this);

		Long count = (Long) query.uniqueResult();
		return count.intValue();
	}
	
	@Transactional
	public void savePost(Post post) {
		dao.saveOrUpdate(post);
	}
	
	@Transactional
	public void deletePost(Post post) {
		dao.delete(post);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getTagline() {
		return tagline;
	}

	public void setTagline(String tagline) {
		this.tagline = tagline;
	}

	public BlogConfiguration getConfiguration() {
		if (configuration == null) {
			configuration = new BlogConfiguration();
		}
		return configuration;
	}

	public void setConfiguration(BlogConfiguration config) {
		this.configuration = config;
	}
}
